(function(angular) {
	'use strict';
	angular.module('fs.waf').factory('companySetlinstService', companySetlinstService);
	companySetlinstService.$inject = [ '$q', 'loggerFactory', 'commonService', 'ajaxServiceFactory', 'modalService', 'gridService', 'arithService', '$filter' ];
	function companySetlinstService($q, loggerFactory, commonService, ajaxServiceFactory, modalService, gridService, arithService, $filter) {
		var log = loggerFactory.getLogger("companySetlinstService"), ajaxService = ajaxServiceFactory.buildAjaxService({
			getCompanySetlinstOptions : {
				url : 'do/cda/dataList/companySetlinstOptions',
				method : 'get'
			},
		});
		
		function initGeneral($scope, ctrl, updateProcessFlag) {
			var defer = $q.defer();
			getCompanySetlinstOptions().then(function(response) {
				// for profSetlinst
				ctrl.txnCcyOptions = angular.copy(response.currencyByFxRateOptions);
				ctrl.setlCcyOptions = angular.copy(response.currencyByFxRateOptions);
				ctrl.crDrOptions = response.crDrOptions;
				ctrl.allPaycodeOptions = response.allPaycodeOptions;
				ctrl.itemTypeOptions = response.itemTypeOptions;
				
				defer.resolve();
			}, angular.noop);
			
			ctrl.companyCodeChanged = function(value) {
				if (ctrl.companySetlinst.companyCode) {
					ctrl.custCodeParam = ctrl.companySetlinst.companyCode;
				}
			};
			
			return defer.promise;
		}
		function getCompanySetlinstOptions() {
			var defer = $q.defer();
			ajaxService.getCompanySetlinstOptions().then(function(response) {
				var companySetlinstOptions = {};
				if (response.data) {
					angular.forEach(response.data, function(value, key) {
						var tempValue = {};
						tempValue = value;
						companySetlinstOptions[key] = tempValue;
					});
				}
				defer.resolve(companySetlinstOptions);
			});
			return defer.promise;
		}
		
		
		function initProfSetlinst($scope, ctrl, updateProcessFlag) {
			//init profSetlinst grid
			if(ctrl.validatorConfig) ctrl.layoutConfig.formConfigs.profSetlinst.tableConfigs.table.validatorConfig = ctrl.validatorConfig.profSetlinsts;
			ctrl.profSetlinstInnerGridOptions = gridService.createInnerGridOptions($scope, ctrl.layoutConfig.formConfigs.profSetlinst.tableConfigs.table, profSetlinstRowSelectionChanged);
			ctrl.profSetlinstInnerGridOptions.data = 'vm.companySetlinst.profSetlinsts';
			ctrl.profSetlinstInnerGridOptions.verifyData = 'vm.companySetlinstOld.profSetlinsts';
			ctrl.profSetlinstInnerGridOptions.operationRowHeaderWidth = 50;
			// hidden add when subline
			ctrl.profSetlinstInnerGridOptions.filterRowOperation = function(row, type){
			      if(row && row.entity && row.entity.isMaster == 'N' && type == 'add') {
			    	  return true;
			      } else {
			    	  return false;// default show
			      }
		     };
			function profSetlinstRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedProfSetlinsts = selectedRows;
			}
			
			ctrl.custAcctChanged = function ( rowObj, formCtrl, isInitialized){
				ctrl.companySetlinst.profSetlinsts = ctrl.companySetlinst.profSetlinsts || [];
				rowObj.custAcctId = $filter('encode')(rowObj.custAcctId);
				if(rowObj && !isInitialized && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			
			ctrl.txnCcyChanged = function(rowObj, form) {
				if (rowObj.txnCcy) {
					resetHiddenTxnCcy(rowObj, ctrl);
					if (!checkPrimaryKey(rowObj, ctrl)) return;
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			ctrl.itemTypeChanged = function(rowObj, form) {
				if (rowObj.itemType) {
					if (!checkPrimaryKey(rowObj, ctrl)) return;
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			ctrl.crDrChanged = function(rowObj, form) {
				// if setlCcy change, first clean
				rowObj.paycodeExtProperty = {};
				if (rowObj.crDr) {
					if (!checkPrimaryKey(rowObj, ctrl)) return;
					// reset paycodeOptions.data
					resetPaycodeBySetlCcyAndCrDr(rowObj, ctrl);
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			function checkPrimaryKey(rowObj, ctrl) {
				if (rowObj.txnCcy && rowObj.itemType && rowObj.crDr) {
					angular.forEach(ctrl.companySetlinst.profSetlinsts, function(profSetlinst, index) {
						if (!profSetlinst.itemType || !profSetlinst.crDr || rowObj.$$hashKey == profSetlinst.$$hashKey) return;
						var filterPrimaryKey = profSetlinst.txnCcy + ":" + profSetlinst.itemType + ":" + profSetlinst.crDr;
						if ((rowObj.txnCcy + ":" + rowObj.itemType + ":" + rowObj.crDr) == filterPrimaryKey) {
							// changed eventCode has used
							if (rowObj.isMaster == 'Y') {
								rowObj.txnCcy = '';
							} else {
								rowObj.itemType = '';
								rowObj.crDr = '';
							}
							modalService.openErrorDialogs({
								messages : [ 'js.info.profsetlinst.duplicate-txnccy-itemtype-creditordebit' ]
							});
							return false;
						}
					});
				}
				return true;
			}
			function resetHiddenTxnCcy(rowObj, ctrl) {
				var currIndex;
				angular.forEach(ctrl.companySetlinst.profSetlinsts, function(profSetlinst, index) {
					if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
						currIndex = index;
					}
				});
				if (currIndex + 1 < ctrl.companySetlinst.profSetlinsts.length) {
					for (var i = currIndex + 1; i < ctrl.companySetlinst.profSetlinsts.length; i++) {
						if (ctrl.companySetlinst.profSetlinsts[i].isMaster == 'Y') {
							break;
						}
						ctrl.companySetlinst.profSetlinsts[i].txnCcy = rowObj.txnCcy;
					}
				}
			}
			
			ctrl.setlCcyChanged = function(rowObj, form) {
				// if setlCcy change, first clean
				rowObj.paycodeExtProperty = {};
				// reset paycodeOptions.data
				if (rowObj.setlCcy) {
					resetPaycodeBySetlCcyAndCrDr(rowObj, ctrl);
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			
			function resetPaycodeBySetlCcyAndCrDr(rowObj, ctrl) {
				if (!rowObj.setlCcy || !rowObj.crDr) return;
				// filter intRateIndex by ccy
				var paycodeOptionDatas = [];
				for (var i = 0; i < ctrl.allPaycodeOptions.length; i++) {
					var _paycodeOption = ctrl.allPaycodeOptions[i];
					if ((_paycodeOption.payCcy == rowObj.setlCcy || _paycodeOption.payCcy == '*') && 
							(_paycodeOption.usedFor == 'B' || rowObj.crDr == 'B' ||  _paycodeOption.usedFor == rowObj.crDr)) {
						paycodeOptionDatas.push(ctrl.allPaycodeOptions[i]);
					}
				}
				if (rowObj._paycodeConfig && rowObj._paycodeConfig.options)
					rowObj._paycodeConfig.options.data = paycodeOptionDatas;
				if (rowObj._paycodeConfig && rowObj._paycodeConfig.options && rowObj._paycodeConfig.options.data) {
					for (var i = 0; i < rowObj._paycodeConfig.options.data.length; i++) {
						var _paycodeOption = rowObj._paycodeConfig.options.data[i];
						if (_paycodeOption.value == rowObj.paycode) {
							ctrl.paycodeChanged(rowObj);
							break;
						}
					}
				}
			}
			
			ctrl.paycodeChanged = function(rowObj, form) {
				if (rowObj.paycode) {
					resetSetlByPaycode(rowObj, ctrl, true);
				} else {
					// if no paycode, need clear
					rowObj.paycodeExtProperty = {};
					if (rowObj.isMaster != 'Y')rowObj.acctNo = '';
					rowObj.custAcctId = '';
				}
				//
				if(form && form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			
			function resetSetlByPaycode(rowObj, ctrl, changed) {
				if (rowObj._paycodeConfig && rowObj._paycodeConfig.options && rowObj._paycodeConfig.options.data) {
					for (var i = 0; i < rowObj._paycodeConfig.options.data.length; i++) {
						var _paycodeOption = rowObj._paycodeConfig.options.data[i];
						if (_paycodeOption.value == rowObj.paycode) {
							rowObj.paycodeExtProperty = _paycodeOption;
							// if "Y", acctNo is Customer Account Type
							if (rowObj.paycodeExtProperty.custAcctFlag == 'N') {
								rowObj.acctNo = rowObj.paycodeExtProperty.acctNo;
								rowObj.custAcctId = '';
							} else if (rowObj.paycodeExtProperty.custAcctFlag == 'Y') {
								rowObj.custAcctType = rowObj.paycodeExtProperty.acctNo;
								if (changed) {
									if (rowObj.isMaster != 'Y' && !rowObj.custAcctId)
										rowObj.acctNo = '';// if change need clear, but if init need contain
								}
							}
							break;
						}
					}
				}
			}
			
			ctrl.isDefaultChanged = function(rowObj) {
				if (rowObj.isDefault && rowObj.isDefault.length == 1 && rowObj.isDefault[0] == 'Y') {
					ctrl.companySetlinst.defSetlinstTxnCcy = rowObj.txnCcy;
					// other must 'N'
					angular.forEach(ctrl.companySetlinst.profSetlinsts, function(profSetlinst, index) {
						if (profSetlinst.$$hashKey != rowObj.$$hashKey) {
							profSetlinst.isDefault = [];
						}
					});
				}
			}
			
			ctrl.acctNoMoreData = function (rowObj){
				var params = {};
				// for get dynaparm page
				params.custAcctId = rowObj.custAcctId;
				if (!params.custAcctId) {
					modalService.openErrorDialogs({
						messages : [ 'js.info.profsetlinst.account-need-first-select' ]
					});
					return;
				}
				modalService.openCustomDialogs({
				   'title': 'title.popup.view.custaccount',
				   'dialogsModule' : 'cda.custacct.popupview',
				   'params': params,
				   'btnCallback' : {
						'ok' : function(resultList) {
						}
					}	
				});
			};
			
			ctrl.addProfSetlinst = function() {
				return $q(function(resolved, rejected){
					if (!ctrl.companySetlinst.profSetlinsts) {
						ctrl.companySetlinst.profSetlinsts = [];
					}
					for (var i = 0; i < ctrl.companySetlinst.profSetlinsts.length; i++) {
						var rowObj = ctrl.companySetlinst.profSetlinsts[i];
						if (!rowObj.txnCcy) {
							modalService.openErrorDialogs({
								messages : [ 'js.info.profsetlinst.txnccy-need-first-select' ]
							});
							return;
						}
					}
					// add master
					ctrl.companySetlinst.profSetlinsts.push({
						dataStatus : 'C',
						dataStatusDisp : '',
						isMaster : 'Y',
						// for validation
						itemType : 'N',
						crDr : 'N',
						setlCcy : 'N',
						paycode : 'N',
						acctNo : 'N'
					});
					// add sub line
					var newSubLine = {
						txnCcy : '',
						dataStatus : 'C',
						dataStatusDisp : 'C',
						isMaster : 'N',
						_paycodeConfig : {
						     model : "paycode",
						     type : "select",
						     options : {
						    	 "callback":{"changed" : "vm.paycodeChanged"}
						     },
						     show: "row.entity.isMaster == 'N'",
						     uppercase : true
						}
					};
					ctrl.companySetlinst.profSetlinsts.push(newSubLine);
					rejected();
				});
			};
			
			ctrl.removeProfSetlinst = function(currRow) {
				return $q(function(resolved, rejected){
					var rowObj = currRow.entity;
					if (rowObj.isMaster == 'Y') {
						deleteMasterLine(ctrl, rowObj);
					} else {
						ctrl.deleteSubLine(rowObj);
					}
					rejected();
				});
			};
			
			 function deleteMasterLine(ctrl, rowObj) {
				var needDeleteRows = [];
				needDeleteRows.push(rowObj);
				angular.forEach(ctrl.companySetlinst.profSetlinsts, function(profSetlinst, index) {
					if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
						rowObj.index = index;
					}
				});
				if (rowObj.isMaster == 'Y' && rowObj.index + 1 < ctrl.companySetlinst.profSetlinsts.length) {
					for (var j = rowObj.index + 1; j < ctrl.companySetlinst.profSetlinsts.length; j++) {
						if (ctrl.companySetlinst.profSetlinsts[j].isMaster == 'Y')
							break;
						needDeleteRows.push(ctrl.companySetlinst.profSetlinsts[j]);
					}
				}
				angular.forEach(needDeleteRows, function(selectedProfSetlinst, key) {
					angular.forEach(ctrl.companySetlinst.profSetlinsts, function(profSetlinst, index) {
						if (profSetlinst.$$hashKey == selectedProfSetlinst.$$hashKey) {
							if (profSetlinst.dataStatus =='C') {
								ctrl.companySetlinst.profSetlinsts.splice(index, 1);
							} else {
								profSetlinst.dataStatus = 'D';
								profSetlinst.dataStatusDisp = 'D';
							}
						}
					});
				});
				
				deleteMasterNoSub(ctrl);
			};
			
			ctrl.addSubLine = function (currRow){
				return $q(function(resolved, rejected){
					var rowObj = currRow.entity;
					if (!rowObj.txnCcy) {
						modalService.openErrorDialogs({
							messages : [ 'js.info.profsetlinst.txnccy-need-first-select' ]
						});
						return;
					}
					var currIndex;
					angular.forEach(ctrl.companySetlinst.profSetlinsts, function(profSetlinst, index) {
						if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
							currIndex = index;
						}
					});
					var nextMasterRowIndex;
					if (currIndex + 1 < ctrl.companySetlinst.profSetlinsts.length) {
						for (var i = currIndex + 1; i < ctrl.companySetlinst.profSetlinsts.length; i++) {
							if (ctrl.companySetlinst.profSetlinsts[i].isMaster == 'Y') {
								nextMasterRowIndex = i;
								break;
							}
						}
					}
					if (!nextMasterRowIndex) nextMasterRowIndex = ctrl.companySetlinst.profSetlinsts.length;
					var newSubLine = {
						txnCcy : rowObj.txnCcy,
						dataStatus : 'C',
						dataStatusDisp : 'C',
						isMaster : 'N',
						_paycodeConfig : {
						     model : "paycode",
						     type : "select",
						     options : {
						    	 "callback":{"changed" : "vm.paycodeChanged"}
						     },
						     show: "row.entity.isMaster == 'N'",
						     uppercase : true
						}
					};
					ctrl.companySetlinst.profSetlinsts.splice(nextMasterRowIndex, 0, newSubLine);
					rejected();
				});
			};
			
			ctrl.deleteSubLine = function (rowObj){
				angular.forEach(ctrl.companySetlinst.profSetlinsts, function(profSetlinst, index) {
					if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
						if (profSetlinst.dataStatus =='C') {
							ctrl.companySetlinst.profSetlinsts.splice(index, 1);
						} else {
							profSetlinst.dataStatus = 'D';
							profSetlinst.dataStatusDisp = 'D';
						}
					}
				});
				
				deleteMasterNoSub(ctrl);
			};
			
			// after delete, need check hsa master but no sub, need delete it 
			function deleteMasterNoSub(ctrl) {
				if (ctrl.companySetlinst.profSetlinsts) {
					var lastTxnCcy = '';
					for (var i = ctrl.companySetlinst.profSetlinsts.length - 1; i >= 0; i--) {
						var profSetlinst = ctrl.companySetlinst.profSetlinsts[i];
						if (profSetlinst.isMaster == 'Y' && profSetlinst.txnCcy && (profSetlinst.txnCcy != lastTxnCcy)) {
							ctrl.companySetlinst.profSetlinsts.splice(i, 1);
						}
						
						lastTxnCcy = profSetlinst.txnCcy;
					}
				}
			}
		};
		
		// update reset for page show
		function resetSetlinstByData(initCompanySetlinst, isView) {
			var initProfSetlinsts = initCompanySetlinst.profSetlinsts;
			var needProfSetlinstModels = [];
			var txnCcyMap = {};
			angular.forEach(initProfSetlinsts, function(profSetlinst, index) {
				// real data and add _paycodeConfig
				profSetlinst.isMaster = 'N';
				profSetlinst._paycodeConfig = {
						model : "paycode",
						type : "select",
						options : {
							"callback":{"changed" : "vm.paycodeChanged"}
						},
						show: "row.entity.isMaster == 'N'",
						uppercase : true
				};
				profSetlinst.dataStatusDisp = profSetlinst.dataStatus;
				if (isView) profSetlinst._paycodeConfig.readonly = true;
				// txnCcyMap
				if (txnCcyMap[profSetlinst.txnCcy]) {
					txnCcyMap[profSetlinst.txnCcy].push(profSetlinst);
				} else {
					txnCcyMap[profSetlinst.txnCcy] = [];
					txnCcyMap[profSetlinst.txnCcy].push(profSetlinst);
				}
			});
			
			// build virtual master line
			angular.forEach(txnCcyMap, function(txnCcyMapValue, key) {
				var profSetlinstMaster = {};
				profSetlinstMaster.isMaster = 'Y';
				profSetlinstMaster.txnCcy = key;
				if (initCompanySetlinst.defSetlinstTxnCcy && initCompanySetlinst.defSetlinstTxnCcy == key) {
					profSetlinstMaster.isDefault = [];
					profSetlinstMaster.isDefault[0] = 'Y';
				}
				var txnCcyProfSetlinsts = txnCcyMap[key];
				for (var i = 0; i < txnCcyProfSetlinsts.length; i++) {
					var txnCcyProfSetlinst = txnCcyProfSetlinsts[i];
					if ("V" == txnCcyProfSetlinst.dataStatus || "U" == txnCcyProfSetlinst.dataStatus || "D" == txnCcyProfSetlinst.dataStatus) {
						profSetlinstMaster.dataStatus = "V";
						break;
					}
				}
				// itemType : 'N', crDr : 'N', setlCcy : 'N', paycode : 'N', acctNo : 'N',
				profSetlinstMaster.itemType = 'N';
				profSetlinstMaster.crDr = 'N';
				profSetlinstMaster.setlCcy = 'N';
				profSetlinstMaster.paycode = 'N';
				profSetlinstMaster.acctNo = 'N';
				needProfSetlinstModels.push(profSetlinstMaster);
				for (var i = 0; i < txnCcyProfSetlinsts.length; i++) {
					needProfSetlinstModels.push(txnCcyProfSetlinsts[i]);
				}
			});
			initCompanySetlinst.profSetlinsts = needProfSetlinstModels;
		}
		
		function clearDirtyData (companySetlinst) {
			// delete build virtual master line when submit to server
			if (companySetlinst.profSetlinsts != null && companySetlinst.profSetlinsts.length > 0) {
				for (var i = companySetlinst.profSetlinsts.length - 1; i >= 0; i--) {
					if ("Y" == companySetlinst.profSetlinsts[i].isMaster) {
						companySetlinst.profSetlinsts.splice(i, 1);
					}
				}
			}
		}
		
		return {
			initGeneral : initGeneral,
			initProfSetlinst : initProfSetlinst,
			resetSetlinstByData : resetSetlinstByData,
			clearDirtyData : clearDirtyData
		};
	}
})(angular);